package com.game.curator;

import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.game.config.NodeConfig;

public class MarsNode {
    private String nodePath;

    private String nodeData;

    private NodeConfig nodeConfig;

    private Map<String, MarsNode> childrenNodes = new HashMap<>();

    public MarsNode(String nodePath, String nodeData) {
        this.nodePath = nodePath;
        this.nodeData = nodeData;
    }

    public MarsNode addChildren(MarsNode marsNode) {
        MarsNode mn = getChildren(marsNode.getNodePath(), false);
        if (mn == null || mn.getNodePath().equals(marsNode.getNodePath()))
            return this.childrenNodes.put(marsNode.getNodePath(), marsNode);
        return mn.addChildren(marsNode);
    }

    public MarsNode removeChildren(String path) {
        if (this.childrenNodes.containsKey(path))
            return this.childrenNodes.remove(path);
        MarsNode marsNode = getChildren(path, false);
        if (marsNode != null)
            return marsNode.removeChildren(path);
        return null;
    }

    public MarsNode getChildren(String path, boolean rc) {
        if (!this.childrenNodes.isEmpty())
            for (MarsNode marsNode : this.childrenNodes.values()) {
                if (path.equals(marsNode.getNodePath()))
                    return marsNode;
                if (path.startsWith(marsNode.getNodePath())) {
                    if (rc)
                        return marsNode.getChildren(path, rc);
                    return marsNode;
                }
            }
        return null;
    }

    public List<MarsNode> getAllChildren() {
        return new ArrayList<>(this.childrenNodes.values());
    }

    public MarsNode randomOneMarsNode() {
        if (this.childrenNodes.isEmpty())
            return null;
        List<MarsNode> childrens = getAllChildren();
        Random random = new Random();
        int p = random.nextInt(childrens.size());
        return childrens.get(p);
    }

    public MarsNode randomOneMarsNodeWithWeight(String ip, long id) {
        if (this.childrenNodes.isEmpty())
            return null;
        List<MarsNode> childrens = getAllChildren();
        List<MarsNode> tempNodes = new ArrayList<>();
        List<MarsNode> preciselist = new ArrayList<>();
        for (MarsNode marsNode : childrens) {
            NodeConfig nodeConfig = marsNode.getNodeConfig();
            if ((nodeConfig.whiteIdList == null || nodeConfig.whiteIdList.length == 0) && (nodeConfig.whiteIpList == null || nodeConfig.whiteIpList.length == 0)) {
                tempNodes.add(marsNode);
                continue;
            }
            if (ClusterHelper.preciseInIdWhiteList(id, nodeConfig.whiteIdList) || ClusterHelper.preciseInIpWhiteList(ip, nodeConfig.whiteIpList))
                preciselist.add(marsNode);
        }
        if (!preciselist.isEmpty())
            tempNodes = preciselist;
        if (tempNodes.isEmpty())
            return null;
        int totalWeight = tempNodes.stream().mapToInt(m -> (m.getNodeConfig()).weight).sum();
        if (totalWeight <= 0)
            return null;
        Random random = new Random();
        int p = random.nextInt(totalWeight);
        int sum = 0;
        for (MarsNode marsNode : tempNodes) {
            sum += (marsNode.getNodeConfig()).weight;
            if (p < sum)
                return marsNode;
        }
        System.out.println("===========================");
        System.out.println("==根据权重寻找节点失败" );
                System.out.println("===========================");
        return null;
    }

    public boolean hasChildren() {
        return !this.childrenNodes.isEmpty();
    }

    public String getNodePath() {
        return this.nodePath;
    }

    public void setNodePath(String nodePath) {
        this.nodePath = nodePath;
    }

    public String getNodeData() {
        return this.nodeData;
    }

    public NodeConfig getNodeConfig() {
        if (this.nodeConfig == null && this.nodeData != null && !this.nodeData.isEmpty())
            try {
                this.nodeConfig = (NodeConfig)JSON.parseObject(this.nodeData, NodeConfig.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        return this.nodeConfig;
    }

    public void updateData(String data) {
        this.nodeData = data;
        this.nodeConfig = null;
        getNodeConfig();
    }

    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (!(o instanceof MarsNode))
            return false;
        MarsNode marsNode = (MarsNode)o;
        return this.nodePath.equals(marsNode.nodePath);
    }

    public int hashCode() {
        return this.nodePath.hashCode();
    }
}
